/**
 *
 * @author Patricia Blanco created 2013 copyright 2013
 */
package dieci.database.rawmaterial;

import dieci.database.PersistentObject;
import dieci.database.SessionFactoryUtil;
import dieci.hibernate.HibOrderRawMaterialDetails;
import dieci.hibernate.HibOrderRawMaterial;
import dieci.managers.supplier.SupplierManager;
import dieci.system.OrderRawMaterial;
import dieci.system.OrderRawMaterialDetails;
import dieci.system.Supplier;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import org.hibernate.Session;
import java.util.logging.Logger;
import org.hibernate.criterion.Restrictions;

public class OrderRawMaterialHibernateDAO implements OrderRawMaterialDAO
{

    private static Logger logger = Logger.getLogger("OrderRawMaterialDAO.log");
    private SupplierManager supplierManager = new SupplierManager();
    
    @Override
    public List<OrderRawMaterial> list()
    {
        List<OrderRawMaterial> orderRawMaterials = new ArrayList<>();

        Session session = SessionFactoryUtil.getInstance().getCurrentSession();
        try {
            session.beginTransaction();

            List<HibOrderRawMaterial> hibOrderRawMaterials = session.createCriteria(HibOrderRawMaterial.class).list();
            for (HibOrderRawMaterial dbOrderRawMaterial : hibOrderRawMaterials) {
                Set<OrderRawMaterialDetails> details = new HashSet<>();
                for (HibOrderRawMaterialDetails hibOrderRawMaterialDetails : dbOrderRawMaterial.getDetails()) {
                    details.add(new OrderRawMaterialDetails(hibOrderRawMaterialDetails.getId().getRawMaterialId(),
                            hibOrderRawMaterialDetails.getAmount(), hibOrderRawMaterialDetails.getCost()));
                }
                Supplier supplier = supplierManager.findById(dbOrderRawMaterial.getSupplierId());
                OrderRawMaterial orderRawMaterial = new OrderRawMaterial(supplier, dbOrderRawMaterial.getOrderRawMaterialDate(), details,dbOrderRawMaterial.getTotalOrderRawMaterialAmount());
                orderRawMaterial.setOrderRawMaterialId(dbOrderRawMaterial.getOrderRawMaterialId());
                orderRawMaterials.add(orderRawMaterial);
            }

            return orderRawMaterials;
        }
        catch (Exception e) {

            logger.log(Level.INFO, "Error listando", e.getMessage());

            throw new IllegalStateException("Error al listar", e);
        }
        finally {
            if (session != null && session.isOpen()) {

                session.close();
            }
        }
    }

    @Override
    public OrderRawMaterial findByOrderRawMaterialId(long id)
    {
        OrderRawMaterial result = null;
        Session session = SessionFactoryUtil.getInstance().getCurrentSession();
        try {
            session.beginTransaction();

            HibOrderRawMaterial hibOrderRawMaterial = (HibOrderRawMaterial) session.createCriteria(HibOrderRawMaterial.class).add(Restrictions.eq("orderRawMaterialId", id)).uniqueResult();
            if (hibOrderRawMaterial != null) {
                Set<OrderRawMaterialDetails> details = new HashSet<>();
                for (HibOrderRawMaterialDetails detail : hibOrderRawMaterial.getDetails()) {

                    OrderRawMaterialDetails p = new OrderRawMaterialDetails(detail.getId().getRawMaterialId(), detail.getAmount(), detail.getCost());
                    p.setOrderRawMaterialId(detail.getId().getOrderRawMaterialId());
                    details.add(p);
                }
                Supplier supplier = supplierManager.findById(hibOrderRawMaterial.getSupplierId());
                result = new OrderRawMaterial(supplier,
                        hibOrderRawMaterial.getOrderRawMaterialDate(), details, hibOrderRawMaterial.getTotalOrderRawMaterialAmount());
                result.setOrderRawMaterialId(hibOrderRawMaterial.getOrderRawMaterialId());
            }

        }
        catch (Exception e) {
            throw new IllegalStateException("Error al buscar por articulo", e);
        }
        finally {
            if (session != null && session.isOpen()) {

                session.close();
            }
        }

        return result;
    }

    @Override
    public void delete(PersistentObject object)
    {
        Session session = null;

        OrderRawMaterial orderRawMaterial = (OrderRawMaterial) object;
        OrderRawMaterial found = findByOrderRawMaterialId(orderRawMaterial.getOrderRawMaterialId());
        try {
            session = SessionFactoryUtil.getInstance().getCurrentSession();

            session.beginTransaction();

            if (found != null) {
                //DELETE
                orderRawMaterial.setOrderRawMaterialId(found.getOrderRawMaterialId());

                Set<HibOrderRawMaterialDetails> hibOrderRawMaterialDetailss = new HashSet<>();
                for (OrderRawMaterialDetails detail : orderRawMaterial.getDetails()) {
                    HibOrderRawMaterialDetails p = new HibOrderRawMaterialDetails(detail, orderRawMaterial.getOrderRawMaterialId());
                    hibOrderRawMaterialDetailss.add(p);
                }
                HibOrderRawMaterial hibOrderRawMaterial = new HibOrderRawMaterial(orderRawMaterial.getOrderRawMaterialId(), (OrderRawMaterial) orderRawMaterial);
                hibOrderRawMaterial.setDetails(hibOrderRawMaterialDetailss);
                session.delete(hibOrderRawMaterial);

            }

            session.getTransaction().commit();

        }
        catch (Exception e) {
            if (session != null) {
                session.getTransaction().rollback();
            }
            throw new IllegalStateException("Error al eliminar", e);
        }
        finally {
            if (session != null && session.isOpen()) {

                session.close();
            }
        }
    }

    @Override
    public void saveOrUpdate(PersistentObject object)
    {
        Session session = null;

        OrderRawMaterial orderRawMaterial = (OrderRawMaterial) object;
        OrderRawMaterial found = null;

        if (orderRawMaterial.getOrderRawMaterialId() > 0) {
            found = findByOrderRawMaterialId(orderRawMaterial.getOrderRawMaterialId());
        }

        try {
            session = SessionFactoryUtil.getInstance().getCurrentSession();

            session.beginTransaction();

            if (found != null) {
                //UPDATE
                orderRawMaterial.setOrderRawMaterialId(found.getOrderRawMaterialId());

                Set<HibOrderRawMaterialDetails> hibOrderRawMaterialDetailss = new HashSet<>();
                for (OrderRawMaterialDetails detail : orderRawMaterial.getDetails()) {
                    HibOrderRawMaterialDetails d = new HibOrderRawMaterialDetails(detail, orderRawMaterial.getOrderRawMaterialId());
                    hibOrderRawMaterialDetailss.add(d);
                }
                HibOrderRawMaterial hibOrderRawMaterial = new HibOrderRawMaterial(orderRawMaterial.getOrderRawMaterialId(), (OrderRawMaterial) orderRawMaterial);
                hibOrderRawMaterial.setDetails(hibOrderRawMaterialDetailss);
                session.saveOrUpdate(hibOrderRawMaterial);

            }
            else {
                //NEW
                HibOrderRawMaterial hibOrderRawMaterial = new HibOrderRawMaterial(orderRawMaterial);

                // generate new id for the orderRawMaterialuct
                session.save(hibOrderRawMaterial);
                // add the details
                for (OrderRawMaterialDetails detail : orderRawMaterial.getDetails()) {
                    hibOrderRawMaterial.getDetails().add(
                            new HibOrderRawMaterialDetails(detail, hibOrderRawMaterial.getOrderRawMaterialId()));
                }

                // If the enty already exist update it.
                session.saveOrUpdate(hibOrderRawMaterial);
            }

            session.getTransaction().commit();

        }
        catch (Exception e) {
            if (session != null) {
                session.getTransaction().rollback();
            }
            throw new IllegalStateException("Error al guardar o actualizar", e);
        }
        finally {
            if (session != null && session.isOpen()) {

                session.close();
            }
        }
    }

    @Override
    public List<OrderRawMaterial> findByOrderRawMaterialDateRange(Date start, Date end)
    {
        List<OrderRawMaterial> orderRawMaterials = new ArrayList<>();

        Session session = SessionFactoryUtil.getInstance().getCurrentSession();
        try {
            session.beginTransaction();

            List<HibOrderRawMaterial> hibOrderRawMaterials = session.createCriteria(HibOrderRawMaterial.class).add(Restrictions.between("orderRawMaterialDate", start, end)).list();
            for (HibOrderRawMaterial dbOrderRawMaterial : hibOrderRawMaterials) {
                Set<OrderRawMaterialDetails> details = new HashSet<>();
                for (HibOrderRawMaterialDetails hibOrderRawMaterialDetails : dbOrderRawMaterial.getDetails()) {
                    details.add(new OrderRawMaterialDetails(hibOrderRawMaterialDetails.getId().getRawMaterialId(),
                            hibOrderRawMaterialDetails.getAmount(), hibOrderRawMaterialDetails.getCost()));
                }
                Supplier supplier = supplierManager.findById(dbOrderRawMaterial.getSupplierId());
                OrderRawMaterial orderRawMaterial = new OrderRawMaterial(supplier, dbOrderRawMaterial.getOrderRawMaterialDate(), details, dbOrderRawMaterial.getTotalOrderRawMaterialAmount());
                orderRawMaterial.setOrderRawMaterialId(dbOrderRawMaterial.getOrderRawMaterialId());
                orderRawMaterials.add(orderRawMaterial);
            }

            return orderRawMaterials;
        }
        catch (Exception e) {

            logger.log(Level.INFO, "Error listando compras por fecha", e.getMessage());

            throw new IllegalStateException("Error al listar", e);
        }
        finally {
            if (session != null && session.isOpen()) {

                session.close();
            }
        }
    }

    @Override
    public List<OrderRawMaterial> findBySupplierName(String supplierName)
    {
        List<OrderRawMaterial> orderRawMaterials = new ArrayList<>();

        Session session = null;
        
        try 
        {
            List<Supplier> suppliers = new SupplierManager().find(supplierName);

            session = SessionFactoryUtil.getInstance().getCurrentSession();
            session.beginTransaction();
            
            for (Supplier supplier : suppliers) {
                List<HibOrderRawMaterial> hibOrderRawMaterials = session.createCriteria(HibOrderRawMaterial.class).add(Restrictions.like("supplierId", supplier.getSupplierId())).list();
                for (HibOrderRawMaterial dbOrderRawMaterial : hibOrderRawMaterials) {
                    Set<OrderRawMaterialDetails> details = new HashSet<>();
                    for (HibOrderRawMaterialDetails hibOrderRawMaterialDetails : dbOrderRawMaterial.getDetails()) {
                        details.add(new OrderRawMaterialDetails(hibOrderRawMaterialDetails.getId().getRawMaterialId(),
                                hibOrderRawMaterialDetails.getAmount(), hibOrderRawMaterialDetails.getCost()));
                    }
                    OrderRawMaterial orderRawMaterial = new OrderRawMaterial(supplier, dbOrderRawMaterial.getOrderRawMaterialDate(), details,
                            dbOrderRawMaterial.getTotalOrderRawMaterialAmount());
                    orderRawMaterial.setOrderRawMaterialId(dbOrderRawMaterial.getOrderRawMaterialId());
                    orderRawMaterials.add(orderRawMaterial);
                }
            }


            return orderRawMaterials;
        }
        catch (Exception e) {

            logger.log(Level.INFO, "Error listando compras para el proveedor " + supplierName, e.getMessage());

            throw new IllegalStateException("Error al listar", e);
        }
        finally {
            if (session != null && session.isOpen()) {

                session.close();
            }
        }
    }
}
